pub mod db_category;
pub mod db_classroom;
pub mod db_knowledge;
pub mod db_knowledge_progress;
pub mod db_scheduler;
pub mod db_school;
pub mod db_student;
pub mod db_subject;
pub mod db_task;
pub mod db_task_knowledge;
pub mod db_teacher;

pub mod entities;

use std::sync::Mutex;

use lazy_static::lazy_static;
use log::{info, trace};
use rbase_iam::db::define::SYSTEM_ID;
use sea_orm::DatabaseConnection;

use serde::Deserialize;
use tokio::runtime::Runtime;

use anyhow::{Ok, Result};

use crate::db::entities::subject;

pub static CONNECTION: Mutex<Option<DatabaseConnection>> = Mutex::new(None);

lazy_static! { // You can also use `once_cell`
    static ref RT: Runtime = Runtime::new().unwrap();
}

pub async fn init() -> Result<()> {
    info!("Initializing database");

    db_category::init_tables().await?;
    db_classroom::init_tables().await?;
    db_knowledge::init_tables().await?;
    db_scheduler::init_tables().await?;
    db_knowledge_progress::init_tables().await?;
    db_school::init_tables().await?;
    db_student::init_tables().await?;
    db_subject::init_tables().await?;
    db_task::init_tables().await?;
    db_task_knowledge::init_tables().await?;
    db_teacher::init_tables().await?;

    load_default_subjects().await?;

    Ok(())
}

#[derive(Debug, Deserialize)]
struct TempSubject {
    pub name: String,
}
pub async fn load_default_subjects() -> Result<()> {
    info!("Loading default subjects");

    let input_json: &[u8] = include_bytes!("../../resources/subjects.json");
    let subjects: Vec<TempSubject> = serde_json::from_slice(input_json)?;

    for subject in subjects {
        if db_subject::find_by_name(&subject.name).await?.is_some() {
            continue;
        }

        trace!("Inserting subject: {:?}", subject);
        db_subject::insert(subject::Model {
            name: Some(subject.name),
            owner_id: Some(SYSTEM_ID),
            ..Default::default()
        })
        .await?;
    }

    Ok(())
}
